﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ShadowCommando.Game;
using ShadowCommando.Game.Elements;
using ShadowCommando.Game.Elements.Obstacle;
using ShadowCommando.Game.Elements.Enemies;
using ShadowCommando.Game.GameBoard;
using ShadowCommando.Game.GameGraphics;
using ShadowCommando.Game.Utilites.Map;
using ShadowCommando.Game.Elements.Bonus;
using System.Configuration;

using System.Drawing;
namespace ShadowCommando.Game.Utilites
{
    /// <summary>
    /// Klasa odpowiadająca za ustawienia map
    /// </summary>
   public class MapSettings
   {
       private int mapWidth;
       private int mapHeight;
       private int mapLvl;
       private GameBoard.Board board;

       private LevelDifficulty difficulty;
       private Dictionary<ObstacleId, int> obstaclesDictionary;
       private Dictionary<EnemyId, int> enemiesDictionary;
       private Dictionary<ObstacleId, int> aimDictionary;
       private Dictionary<BonusId, int> bonusDictionary;
        private int leftGap=MapSetinggs.Default.leftGap;
        private int rightGap=MapSetinggs.Default.rightGap;
       private int step;
       GameGraphics.GameGraphic gameGraphics=new GameGraphic();

       /// <summary>
       /// Konstruktor
       /// </summary>
       /// <param name="_mapLvl">Poziom mapy</param>
       /// <param name="_mapWidth">Szerokość</param>
       /// <param name="_mapHeight">Wysokość</param>
       /// <param name="_step">Krok</param>
       /// <param name="_difficulty">Poziom trudności</param>
       public MapSettings(int _mapLvl, int _mapWidth, int _mapHeight, int _step, LevelDifficulty _difficulty)
       {
            difficulty = _difficulty;
           board=new Board(_mapWidth,_mapHeight,_step);
           mapHeight = _mapHeight;
           mapWidth = _mapWidth;
           mapLvl = _mapLvl;
           step = _step;

       }
       /// <summary>
       /// Tworzy mape i ustawie elementy na mapie
       /// </summary>
       /// <param name="hero">Bohater</param>
       /// <param name="listEnemy">Lista przeciwnikow</param>
       /// <param name="listBonus">Lista bonusów</param>
       /// <param name="listObstacle">Lista przeszkód</param>
       /// <param name="listAim">Lista celów</param>
       /// <param name="backColor">Tło</param>
       /// <param name="message">Wiadomość</param>
       public void  CreateMap(Element hero,ref List<Enemy> listEnemy,ref List<Bonus> listBonus,
           ref List<Obstacle> listObstacle,ref List<Obstacle> listAim,ref Color backColor,ref string message)
       {
           
           listEnemy=new List<Enemy>();
           listObstacle=new List<Obstacle>();
           listAim=new List<Obstacle>();
           listBonus=new List<Bonus>();
           message = LoadMessage();
           InitEnemiesDictionary();
           InitObstacleDictionary();
           InitAimDictionary(); 
           InitBonusDictionary();
           Random rnd=new Random();
           board.SetElement(hero);
           board.SetField(hero,true);
           SetBackColor(ref backColor);
           SetAims(listAim);
           
           SetObstacles(listObstacle);

           SetBonuses(listBonus);
           SetEnemies(listEnemy);
       }
       private void InitAimDictionary()
       {
           aimDictionary=new Dictionary<ObstacleId, int>();
           switch (mapLvl)
           {
               case 1:
                   {
                       aimDictionary.Add(GetObstacleId("Building"), Level1.Default.Building);
                       break;
                   }
               case 2:
                   {
                       aimDictionary.Add(GetObstacleId("Laboratory"), Level2.Default.Laboratory);
                       break;
                   }
               case 3:
                   {
                       aimDictionary.Add(GetObstacleId("Building2"), Level3.Default.Building2);
                       break;
                   }
               case 4:
                   {
                       aimDictionary.Add(GetObstacleId("Factory"), Level4.Default.Factory);
                       break;
                   }
               case 5:
                   {
                       aimDictionary.Add(GetObstacleId("Laboratory"), Level5.Default.Laboratory);
                       break;
                   }

           }
       }
       private void SetBackColor(ref Color bColor)
       {
           ApplicationSettingsBase asb;
           switch (mapLvl)
           {
               case 1:
                   {
                       asb = Level1.Default;
                       break;
                   }
               case 2:
                   {
                       asb = Level2.Default;
                       break;
                   }
               case 3:
                   {
                       asb = Level3.Default;
                       break;
                   }
               case 4:
                   {
                       asb = Level4.Default;
                       break;
                   }
               case 5:
                   {
                       asb = Level5.Default;
                       break;
                   }
               default:
                   {
                       return;
                   }
           }
           bColor =(Color) asb["BackColor"];
       }
       private void InitEnemiesDictionary()
       {
           enemiesDictionary=new Dictionary<EnemyId, int>();
           ApplicationSettingsBase asb;
           switch (mapLvl)
           {
               case 1:
                   {
                       asb = Level1.Default;
                       break;
                   }
               case 2:
                   {
                       asb = Level2.Default;
                       break;
                   }
               case 3:
                   {
                       asb = Level3.Default;
                       break;
                   }
               case 4:
                   {
                       asb = Level4.Default;
                       break;
                   }
               case 5:
                   {
                       asb = Level5.Default;
                       break;
                   }

               default:
                   {
                       return;
                   }
           }

           enemiesDictionary.Add(GetEnemyId("DroidB1"),(int)asb["DroidB1"]);
           enemiesDictionary.Add(GetEnemyId("DroidB2"), (int)asb["DroidB2"]);
           enemiesDictionary.Add(GetEnemyId("Droideka"), (int)asb["Droideka"]);

       }
       private void InitBonusDictionary()
       {
           bonusDictionary=new Dictionary<BonusId, int>();
           ApplicationSettingsBase asb;
           switch (mapLvl)
           {
               case 1:
                   {
                       asb = Level1.Default;
                       break;
                   }
               case 2:
                   {
                       asb = Level2.Default;
                       break;
                   }
               case 3:
                   {
                       asb = Level3.Default;
                       break;
                   }
               case 4:
                   {
                       asb = Level4.Default;
                       break;
                   }
               case 5:
                   {
                       asb = Level5.Default;
                       break;
                   }
               default:
                   {
                      
                       return;
                   }
           }
           bonusDictionary.Add(BonusId.MedicalKit, (int)asb["MedicalKit"]);
           bonusDictionary.Add(BonusId.Armor, (int)asb["Armor"]);
           bonusDictionary.Add(BonusId.Ammuntion, (int)asb["Ammunition"]);
       }

       private void InitObstacleDictionary()
       {
           obstaclesDictionary=new Dictionary<ObstacleId, int>();
           switch (mapLvl)
           {
               case 1:
                   {
                       LoadObstacleLevel1();
                       break;
                   }
               case 2:
                   {
                       LoadObstacleLevel2();
                       break;
                   }
               case 3:
                   {
                       LoadObstacleLevel3();
                       break;
                   }
               case 4:
                   {
                       LoadObstacleLevel4();

                       break;
                   }
               case 5:
                   {
                       LoadObstacleLevel5();
                       break;
                   }
               default:
                   {
                       return;
                   }
           }
       }
       private void LoadObstacleLevel1()
       {
           obstaclesDictionary.Add(GetObstacleId("Tree1"), Level1.Default.Tree1);
           obstaclesDictionary.Add(GetObstacleId("Tree4"), Level1.Default.Tree4);
            obstaclesDictionary.Add(GetObstacleId("Tree3"), Level1.Default.Tree3);
           obstaclesDictionary.Add(GetObstacleId("Tree2"), Level1.Default.Tree2);
           obstaclesDictionary.Add(GetObstacleId("Tree5"), Level1.Default.Tree5);
           obstaclesDictionary.Add(GetObstacleId("Tree6"), Level1.Default.Tree6);

           obstaclesDictionary.Add(GetObstacleId("Tree7"), Level1.Default.Tree7);
           obstaclesDictionary.Add(GetObstacleId("Lake1"), Level1.Default.Lake1);     
       
       }
       private void LoadObstacleLevel2()
       {
           obstaclesDictionary.Add(GetObstacleId("Palm1"),Level2.Default.Palm1);
           obstaclesDictionary.Add(GetObstacleId("Palm2"), Level2.Default.Palm2);
           obstaclesDictionary.Add(GetObstacleId("Palm3"), Level2.Default.Palm3);
           obstaclesDictionary.Add(GetObstacleId("Palm4"), Level2.Default.Palm4);
           obstaclesDictionary.Add(GetObstacleId("Palm5"), Level2.Default.Palm5);
           obstaclesDictionary.Add(GetObstacleId("Palm6"), Level2.Default.Palm6);

           obstaclesDictionary.Add(GetObstacleId("Branch1"), Level2.Default.Branch1);
           obstaclesDictionary.Add(GetObstacleId("Branch2"), Level2.Default.Branch2);
           obstaclesDictionary.Add(GetObstacleId("Branch3"), Level2.Default.Branch3);
           obstaclesDictionary.Add(GetObstacleId("Branch4"), Level2.Default.Branch4);
       }
       private void LoadObstacleLevel3()
       {
           obstaclesDictionary.Add(GetObstacleId(("Ice1")), Level3.Default.Ice1);
           obstaclesDictionary.Add(GetObstacleId(("Ice2")), Level3.Default.Ice2);
           obstaclesDictionary.Add(GetObstacleId(("Ice3")), Level3.Default.Ice3);
           obstaclesDictionary.Add(GetObstacleId(("Ice4")), Level3.Default.Ice4);
           obstaclesDictionary.Add(GetObstacleId(("Ice5")), Level3.Default.Ice5);
           obstaclesDictionary.Add(GetObstacleId(("Snow1")), Level3.Default.Snow1);
           obstaclesDictionary.Add(GetObstacleId(("Snow2")), Level3.Default.Snow2);
           obstaclesDictionary.Add(GetObstacleId(("SnowTree1")), Level3.Default.SnowTree1);
               
       }
       private void LoadObstacleLevel4()
       {
           obstaclesDictionary.Add(GetObstacleId("Stone1"), Level4.Default.Stone1);
           obstaclesDictionary.Add(GetObstacleId("Stone2"), Level4.Default.Stone2);
           obstaclesDictionary.Add(GetObstacleId("Stone3"), Level4.Default.Stone3);
           obstaclesDictionary.Add(GetObstacleId("Stone4"), Level4.Default.Stone4);
           obstaclesDictionary.Add(GetObstacleId("Stone5"), Level4.Default.Stone5);
           obstaclesDictionary.Add(GetObstacleId("Stone6"), Level4.Default.Stone6);


           obstaclesDictionary.Add(GetObstacleId("Dune1"), Level4.Default.Dune1);

           obstaclesDictionary.Add(GetObstacleId("Palm3"), Level4.Default.Palm3);
           obstaclesDictionary.Add(GetObstacleId("Palm4"), Level4.Default.Palm4);
       }
       private void LoadObstacleLevel5()
       {
           obstaclesDictionary.Add(GetObstacleId("Stone1"), Level5.Default.Stone1);
           obstaclesDictionary.Add(GetObstacleId("Stone2"), Level5.Default.Stone2);
           obstaclesDictionary.Add(GetObstacleId("Stone3"), Level5.Default.Stone3);
           obstaclesDictionary.Add(GetObstacleId("Stone4"), Level5.Default.Stone4);
           obstaclesDictionary.Add(GetObstacleId("Stone5"), Level5.Default.Stone5);
           obstaclesDictionary.Add(GetObstacleId("Stone6"), Level5.Default.Stone6);
           obstaclesDictionary.Add(GetObstacleId("Rock1"), Level5.Default.Rock1);
           obstaclesDictionary.Add(GetObstacleId("Rock2"), Level5.Default.Rock2);

           obstaclesDictionary.Add(GetObstacleId("Dune1"), Level4.Default.Dune1);


           obstaclesDictionary.Add(GetObstacleId("Palm3"), Level5.Default.Palm3);
           obstaclesDictionary.Add(GetObstacleId("Palm4"), Level5.Default.Palm4);
       }
       private string LoadMessage()
       {
           ApplicationSettingsBase asb;
           switch ((mapLvl))
           {
                   
               case 1:
                   {
                       asb = Level1.Default;
                       break;
                   }
               case 2:
                   {
                       asb = Level2.Default;
                       break;
                   }
               case 3:
                   {
                       asb = Level3.Default;
                       break;
                   }
               case 4:
                   {
                       asb = Level4.Default;
                       break;
                   }
               case 5:
                   {
                       asb = Level5.Default;
                       break;
                   }
               default:
                   {
                       return "";
                   }
           }
           return (string)asb["Message"];
       }
       private ObstacleId GetObstacleId(string str)
       {
                foreach(ObstacleId o in Enum.GetValues(typeof(ObstacleId)))
                {
                    if (o.ToString() == str)
                        return o;
                }
           return ObstacleId.Leaf1;
       }
       private EnemyId GetEnemyId(string str)
       {
           foreach (EnemyId o in Enum.GetValues(typeof(EnemyId)))
           {
               if (o.ToString() == str)
                   return o;
           }
           return EnemyId.DroidB1;
       }
       private void SetAims(List<Obstacle> listAim)
       {
           Random rnd=new Random();
           foreach (KeyValuePair<ObstacleId, int> keyValuePair in aimDictionary)
           {
               for (int i = 0; i < keyValuePair.Value; i++)
               {
                   Obstacle o = new Obstacle(step, difficulty, keyValuePair.Key);
                   gameGraphics.SetElementSize(o);
                   o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   board.SetElement(o);
                   int prob = 5;
                   while (board.HasElement(o) && prob != 0)
                   {
                       prob--;
                       o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   }
                   if (prob == 0)
                       continue;
                   board.SetField(o, true);
                   listAim.Add(o);
               }
           }
       }
       private void SetObstacles(List<Obstacle> listObstacle)
       {
           Random rnd =new Random();
           foreach (KeyValuePair<ObstacleId, int> keyValuePair in obstaclesDictionary)
           {
               for (int i = 0; i < keyValuePair.Value; i++)
               {
                   Obstacle o = new Obstacle(step, difficulty, keyValuePair.Key);
                   gameGraphics.SetElementSize(o);
                   o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   board.SetElement(o);
                   int prob = 5;
                   while (board.HasElement(o) && prob != 0)
                   {
                       prob--;
                       o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   }
                   if (prob == 0)
                       continue;
                   board.SetField(o, true);
                   listObstacle.Add(o);
               }
           }
       }
       private void SetEnemies(List<Enemy> listEnemy)
       {
           Random rnd=new Random();
           foreach (KeyValuePair<EnemyId, int> keyValuePair in enemiesDictionary)
           {
               for (int i = 0; i < keyValuePair.Value; i++)
               {
                   Enemy o = new Enemy(step, difficulty,keyValuePair.Key);
                   gameGraphics.SetElementSize(o);
                   o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   board.SetElement(o);
                   int prob = 2;
                   while (board.HasElement(o) && prob != 0)
                   {
                       prob--;
                       o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   }
                   if (prob == 0)
                       continue;
                   board.SetField(o,true);
                   listEnemy.Add(o);
               }
           }
       }
       private void SetBonuses(List<Bonus> listBonus)
       {

           Random rnd = new Random();
           foreach (KeyValuePair<BonusId, int> keyValuePair in bonusDictionary)
           {
               for (int i = 0; i < keyValuePair.Value; i++)
               {
                  Bonus o = new Bonus(step, difficulty, keyValuePair.Key);
                   gameGraphics.SetElementSize(o);
                   o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   board.SetElement(o);
                   int prob = 2;
                   while (board.HasElement(o) && prob != 0)
                   {
                       prob--;
                       o.FakeLocation = new Point(leftGap + rnd.Next(mapWidth - rightGap), leftGap + rnd.Next(mapHeight - rightGap));
                   }
                   if (prob == 0)
                       continue;
                   board.SetField(o,true);
                   listBonus.Add(o);
               }
           }
       }
   }
}
